package controllers;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import models.*;
import play.Logger;
import play.db.DB;
import play.db.jpa.JPABase;
import play.mvc.Controller;

/**
 *
 * @author defk
 */
public class Api extends Controller {

	private static int itemsPerPage = 20;
	private static int pagesPerSearch = 3;

	public static void getUsers() {
	}

	public static void getUser(long id) {
	}

	public static void createPlaylist(Playlist p) {
		User u = Security.getLoggedUser();
		p.user = u == null ? (User) User.findById((long) 1) : u;
		Playlist existing = Playlist.find("byUserAndName", p.user, p.name).first();
		if (existing == null) {
			p.save();
			renderText(p.id);
		} else {
			existing.tracks = p.tracks;
			existing.save();
			renderText(existing.id);
		}
	}

	public static void getPlaylist(long id) {
		Playlist p = Playlist.findById(id);
		renderJSON(p);
	}

	public static void deletePlaylist(long id) {
		Playlist pl = Playlist.findById(id);
		if (pl == null)
			renderText("ok");
		User u = Security.getLoggedUser();
		if (u == null || pl.user.id != u.id)
			renderText("permission denied");
		pl.delete();
		renderText("ok");
	}

	public static void getMyPlaylists() {
		User user = Security.getLoggedUser();
		if (user == null) {
			renderJSON(new HashMap<String, String>().put("error", "not logged"));
		}
		List<Playlist> pls = Playlist.find("byUser", user).fetch();
		renderJSON(pls);
	}

	public static void getRelease(int id) {
		Release r = Release.findById(id);
		if (r.images == null || r.images.isEmpty() || r.images.get(0).url == null)
			Discogs.setReleaseInfo(r);
		for (TrackList trackl : r.trackLists) {
			for (Track t : trackl.tracks) {
				YouTube.saveTrackVideo(t);
			}
		}
		renderJSON(r);
	}

	public static void getArtist(int id) {
		Artist a = Artist.findById(id);
		HashMap<String, Object> m = new HashMap<String, Object>();
		if (a.popis == null || a.popis.equals(""))
			Discogs.setArtistInfo(a);
		m.put("name", a.name);
		m.put("id", a.id);
		m.put("popis", a.popis);
		m.put("image", a.image);
		m.put("releases", Release.find("byArtist", a).fetch());
		renderJSON(m);
	}

	public static void getLabel(int id) {
		Label l = Label.findById(id);
		renderJSON(l);
	}

	public static void getTrack(int id) {
		Track t = Track.findById(id);
		renderJSON(t);
	}

	public static void search(String term) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		List<Artist> as = Artist.find("name like ?", "%" + term + "%").fetch(10);
		map.put("artists", as);
		List<Release> rs = Release.find("name like ?", "%" + term + "%").fetch(10);
		map.put("releases", rs);
		List<Label> ls = Label.find("name like ?", "%" + term + "%").fetch(10);
		map.put("labels", ls);
		List<Track> ts = Track.find("name like ?", "%" + term + "%").fetch(10);
		for (Track t : ts) {
			YouTube.saveTrackVideo(t);
		}
		map.put("tracks", ts);
		renderJSON(map);
	}

	public static void searchArtist(String term, int page) {
		int from = page * itemsPerPage;
		long count = Artist.count("name like ?", "%" + term + "%");
		Map<String, Object> map = paginate(page, count, term);
		List<Artist> as = Artist.find("name like ?", "%" + term + "%").from(from).fetch(itemsPerPage);
		map.put("artists", as);
		renderJSON(map);
	}

	public static void searchRelease(String term, int page) {
		int from = page * itemsPerPage;
		long count = Release.count("name like ?", "%" + term + "%");
		Map<String, Object> map = paginate(page, count, term);
		List<Release> as = Release.find("name like ?", "%" + term + "%").from(from).fetch(itemsPerPage);
		map.put("releases", as);
		renderJSON(map);
	}

	public static void searchLabel(String term, int page) {
		int from = page * itemsPerPage;
		long count = Label.count("name like ?", "%" + term + "%");
		Map<String, Object> map = paginate(page, count, term);
		List<Label> as = Label.find("name like ?", "%" + term + "%").from(from).fetch(itemsPerPage);
		map.put("labels", as);
		renderJSON(map);
	}

	public static void searchTrack(String term, int page) {
		int from = page * itemsPerPage;
		long count = Track.count("name like ?", "%" + term + "%");
		Map<String, Object> map = paginate(page, count, term);
		List<Track> as = Track.find("name like ?", "%" + term + "%").from(from).fetch(itemsPerPage);
		for (Track t : as) {
			YouTube.saveTrackVideo(t);
		}
		map.put("tracks", as);
		renderJSON(map);
	}

	static Map<String, Object> paginate(int page, long count, String query) {
		long maxpage = (int) Math.ceil(count / itemsPerPage);
		List<Map<String, String>> l = new LinkedList<Map<String, String>>();
		maxpage = Math.min(maxpage, page + pagesPerSearch);
		int minpage = Math.max(0, page - pagesPerSearch);
		for (int i = minpage; i <= maxpage; i++) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("n", "" + i);
			map.put("query", query);
			if (i == page) {
				map.put("active", "active");
			}
			l.add(map);
		}

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("pages", l);
		if (page == 0) {
			map.put("prev_disabled", "disabled");
		} else {
			map.put("prev", page - 1);
		}
		if (page == maxpage) {
			map.put("next_disabled", "disabled");
		} else {
			map.put("next", page + 1);
		}
		return map;
	}

	public static void like(int id) {
		User user = Security.getLoggedUser();
		if (user == null) {
			renderText("not logged");
		}
		Track t = Track.findById(id);
		List<Playlist> likes_list = Playlist.find("byNameAndUser", "Likes", user).fetch();
		Playlist likes = null;
		if (likes_list.isEmpty()) {
			likes = new Playlist();
			likes.user = user;
			likes.name = "Likes";
		} else {
			likes = likes_list.get(0);
		}
		if (likes.tracks == null) {
			likes.tracks = new LinkedList<Track>();
		}
		for (Track tr: likes.tracks) {
			if (tr.id == t.id)
				renderText("already set");
		}
		likes.tracks.add(t);
		likes.save();
		renderText("good");
	}

	public static void dislike(int id) {
		User user = Security.getLoggedUser();
		if (user == null) {
			renderText("not logged");
		}
		Track t = Track.findById(id);
		List<Playlist> likes_list = Playlist.find("byNameAndUser", "Dislikes", user).fetch();
		Playlist likes = null;
		if (likes_list.isEmpty()) {
			likes = new Playlist();
			likes.user = user;
			likes.name = "Dislikes";
		} else {
			likes = likes_list.get(0);
		}
		if (likes.tracks == null) {
			likes.tracks = new LinkedList<Track>();
		}
		for (Track tr: likes.tracks) {
			if (tr.id == t.id)
				renderText("already set");
		}
		likes.tracks.add(t);
		likes.save();
		renderText("good");
	}

	public static void mostLiked(int page) {
		try {
			ResultSet rs = DB.executeQuery("select t.id, t.position, t.name, a.name, t.length, t.cache, count(*) as cnt "
					+ "from track t, Playlist p, Playlist_track pt, artist_credit a "
					+ "where t.id = pt.tracks_id and p.id = pt.Playlist_id and t.artist_credit = a.id "
					+ "and p.name = 'Likes' "
					+ "group by t.id, t.position, t.name, a.name, t.length, t.cache "
					+ "order by cnt desc limit 30; ");

			LinkedList<Track> ts = new LinkedList<Track>();
			while (rs.next()) {
				Track t = new Track();
				t.id = rs.getInt(1);
				t.position = rs.getInt(2);
				t.name = rs.getString(3);
				t.artist = new Artist();
				t.artist.name = rs.getString(4);
				t.length = rs.getInt(5);
				t.cache = rs.getString(6);
				ts.addLast(t);
			}
			renderJSON(ts);
		} catch (SQLException ex) {
		}
	}
	public static void mostDisliked(int page) {
		try {
			ResultSet rs = DB.executeQuery("select t.id, t.position, t.name, a.name, t.length, t.cache, count(*) as cnt "
					+ "from track t, Playlist p, Playlist_track pt, artist_credit a "
					+ "where t.id = pt.tracks_id and p.id = pt.Playlist_id and t.artist_credit = a.id "
					+ "and p.name = 'Dislikes' "
					+ "group by t.id, t.position, t.name, a.name, t.length, t.cache "
					+ "order by cnt desc limit 30; ");

			LinkedList<Track> ts = new LinkedList<Track>();
			while (rs.next()) {
				Track t = new Track();
				t.id = rs.getInt(1);
				t.position = rs.getInt(2);
				t.name = rs.getString(3);
				t.artist = new Artist();
				t.artist.name = rs.getString(4);
				t.length = rs.getInt(5);
				t.cache = rs.getString(6);
				ts.addLast(t);
			}
			renderJSON(ts);
		} catch (SQLException ex) {
		}
	}

	public static void wrongVideo(int trackid, String ytid) {
		Track t = Track.findById(trackid);
		t.blacklist += "&" + ytid;
		String[] vids = t.cache.split("&");
		if (vids.length > 1) {
			t.cache = vids[1];
			for (int i = 2; i < vids.length; i++) {
				t.cache += "&" + vids[i];
			}
			t.save();
			renderText(t.cache);
		} else {
			t.cache = "";
			YouTube.saveTrackVideo(t);
			renderText(t.cache);
		}
	}
}
